/**
 * @file task_center.c
 * @author chushang (email:chushangcs@163.com)
 * @brief 任务中心源文件
 * @version 0.1
 * @date 2025-07-12
 *
 * @copyright Copyright (c) 2025
 *
 */

#include "task_center.h"
#include "stddef.h"

static uint8_t task_index = 0; // 任务索引
static Task    task_instances[MAX_TASK_NUM];

/**
 * @brief 设置任务运行周期
 *
 * @param t          [out] 任务指针
 * @param new_period [in]  任务新周期
 * @return 0：设置失败；非0：任务的旧周期
 */
static uint16_t Task_SetPeriod(Task *t, uint16_t new_period)
{
    uint16_t old_period;
    if (!t)
    {
        return 0;
    }
    old_period    = t->run_period;
    t->run_period = new_period;
    return old_period;
}

/**
 * @brief 获取任务运行计数值
 *
 * @param t [in] 任务指针
 * @return 任务计数值
 */
static uint16_t Task_GetCount(Task *t) { return t->run_count; }

/**
 * @brief 增加任务运行时长计数
 *
 * @param t [out] 任务指针
 * @return 0：操作失败；非0：增加前的计数值
 */
static uint16_t Task_AddCount(Task *t)
{
    uint16_t old_count;
    if (!t)
    {
        return 0;
    }
    old_count = Task_GetCount(t);
    t->run_count++;
    return old_count;
}

/**
 * @brief 清空任务的运行计数值
 *
 * @param t [out] 任务指针
 * @return 0：操作失败；1：清空成功
 */
static uint8_t Task_ClearCount(Task *t)
{
    if (!t)
    {
        return 0;
    }

    t->run_count = 0;
    return 1;
}

/**
 * @brief 设置任务运行状态
 *
 * @param t [out] 任务指针
 * @param ts [in] 任务的新状态
 * @return 0：操作失败；1：设置成功
 */
static uint8_t Task_SetState(Task *t, TaskState ts)
{
    if (!t)
    {
        return 0;
    }
    t->run_state = ts;
    return 1;
}

/**
 * @brief 设置任务的运行函数
 *
 * @param t [out] 任务指针
 * @param cb [in] 运行函数
 * @return 0：操作失败；1：设置成功
 */
static uint8_t Task_SetRunCallback(Task *t, void (*cb)(void))
{
    if (!t)
    {
        return 0;
    }
    t->run_callback = cb;
    return 1;
}

/**
 * @brief 检查任务是否需要运行
 *
 * @param t [in] 任务指针
 * @return 任务需要运行返回1，否则返回0
 */
static uint8_t Task_CheckNeedRun(Task *t)
{
    if (!t)
    {
        return 0;
    }
    return t->run_state == TASK_RUNNING;
}

/**
 * @brief 判断任务已等待的时长是否超时，如果超时表示任务需要运行
 *
 * @param t [in] 任务指针
 * @return 1：超时；0：没有超时
 */
static uint8_t Task_JudgeTimeOut(Task *t)
{
    if (!t)
    {
        return 0;
    }
    return t->run_count >= t->run_period;
}

/**
 * @brief 初始化任务
 *
 * @param tc [in] 任务配置结构体
 * @return NULL：操作失败，没有多余空间；其他值：指向任务的指针
 */
Task *Task_Init(TaskConfig *tc)
{
    if (!tc)
    {
        return NULL;
    }
    if (task_index >= MAX_TASK_NUM)
    {
        return NULL;
    }

    Task *t = &task_instances[task_index++];
    Task_SetState(t, TASK_ABORTED);
    Task_SetPeriod(t, tc->run_period);
    Task_SetRunCallback(t, tc->run_callback);

    return t;
}

/**
 * @brief 任务周期自增
 * @note  确保该函数被周期调用，建议放在定时器中断函数
 */
void Task_Center(void)
{
    for (uint8_t i = 0; i < task_index; i++)
    {
        Task_AddCount(&task_instances[i]);
        if (Task_JudgeTimeOut(&task_instances[i]))
        {
            Task_SetState(&task_instances[i], TASK_RUNNING);
            Task_ClearCount(&task_instances[i]);
        }
    }
}

/**
 * @brief 找到需要运行的任务，执行其运行函数
 * @note  建议将该函数放在主循环
 */
void Task_Run(void)
{
    for (uint8_t i = 0; i < task_index; i++)
    {
        if (Task_CheckNeedRun(&task_instances[i]))
        {
            task_instances[i].run_callback();
            Task_SetState(&task_instances[i], TASK_ABORTED);
        }
    }
}
